﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using Microsoft.Xna.Framework.Content;

namespace Deferred.Library.Scene
{
    /// <summary>
    /// 
    /// </summary>
    public class SceneGraph
    {
        #region Private Fields
        [ContentSerializer(Optional = true)]
        private Camera camera;
        [ContentSerializer(Optional = true)]
        private List<DrawableObject> objects = new List<DrawableObject>();
        [ContentSerializer(Optional = true)]
        private List<Terrain> terrains = new List<Terrain>();
        [ContentSerializer(Optional = true)]
        private List<DirectionalLight> directionalLights = new List<DirectionalLight>();
        [ContentSerializer(Optional = true)]
        private List<PointLight> pointLights = new List<PointLight>();
        [ContentSerializer(Optional = true)]
        private List<SpotLight> spotLights = new List<SpotLight>();
        [ContentSerializer(Optional = true)]
        private List<AmbientLight> ambientLights = new List<AmbientLight>();
        #endregion

        #region Events
        /// <summary>
        /// 
        /// </summary>
        public event DrawableObjectAddedEvent DrawableObjectAdded = delegate { };
        /// <summary>
        /// 
        /// </summary>
        public event TerrainAddedEvent TerrainAdded = delegate { };
        /// <summary>
        /// 
        /// </summary>
        public event DirectionalLightAddedEvent DirectionalLightAdded = delegate { };
        /// <summary>
        /// 
        /// </summary>
        public event PointLightAddedEvent PointLightAdded = delegate { };
        /// <summary>
        /// 
        /// </summary>
        public event SpotLightAddedEvent SpotLightAdded = delegate { };
        /// <summary>
        /// 
        /// </summary>
        public event AmbientLightAddedEvent AmbientLightAdded = delegate { };
        /// <summary>
        /// 
        /// </summary>
        public event DrawableObjectDeletedEvent DrawableObjectDeleted = delegate { };
        /// <summary>
        /// 
        /// </summary>
        public event TerrainDeletedEvent TerrainDeleted = delegate { };
        /// <summary>
        /// 
        /// </summary>
        public event DirectionalLightDeletedEvent DirectionalLightDeleted = delegate { };
        /// <summary>
        /// 
        /// </summary>
        public event PointLightDeletedEvent PointLightDeleted = delegate { };
        /// <summary>
        /// 
        /// </summary>
        public event SpotLightDeletedEvent SpotLightDeleted = delegate { };
        /// <summary>
        /// 
        /// </summary>
        public event AmbientLightDeletedEvent AmbientLightDeleted = delegate { };
        /// <summary>
        /// 
        /// </summary>
        public event EventHandler CameraChanged = delegate { };
        #endregion

        #region Public Properties
        /// <summary>
        /// 
        /// </summary>
        [ContentSerializer(Optional = true)]
        public string Name { get; set; }
        /// <summary>
        /// 
        /// </summary>
        [ContentSerializerIgnore]
        public Camera Camera { get { return camera; } set { camera = value; CameraChanged(this, EventArgs.Empty); } }
        /// <summary>
        /// 
        /// </summary>
        [ContentSerializerIgnore]
        public ReadOnlyCollection<DrawableObject> DrawableObjects { get { return new ReadOnlyCollection<DrawableObject>(objects); } }
        /// <summary>
        /// 
        /// </summary>
        [ContentSerializerIgnore]
        public ReadOnlyCollection<Terrain> Terrains { get { return new ReadOnlyCollection<Terrain>(terrains); } }
        /// <summary>
        /// 
        /// </summary>
        [ContentSerializerIgnore]
        public ReadOnlyCollection<DirectionalLight> DirectionalLights { get { return new ReadOnlyCollection<DirectionalLight>(directionalLights); } }
        /// <summary>
        /// 
        /// </summary>
        [ContentSerializerIgnore]
        public ReadOnlyCollection<PointLight> PointLights { get { return new ReadOnlyCollection<PointLight>(pointLights); } }
        /// <summary>
        /// 
        /// </summary>
        [ContentSerializerIgnore]
        public ReadOnlyCollection<SpotLight> SpotLights { get { return new ReadOnlyCollection<SpotLight>(spotLights); } }
        /// <summary>
        /// 
        /// </summary>
        [ContentSerializerIgnore]
        public ReadOnlyCollection<AmbientLight> AmbientLights { get { return new ReadOnlyCollection<AmbientLight>(ambientLights); } }
        #endregion

        /// <summary>
        /// 
        /// </summary>
        public SceneGraph() : this("") { }

        /// <summary>
        /// 
        /// </summary>
        public SceneGraph(string name)
        {
            this.Name = name;
            Camera = new Camera();
        }

        #region Public Methods
        /// <summary>
        /// 
        /// </summary>
        public void Add(DrawableObject o)
        {
            objects.Add(o);
            DrawableObjectAdded(o);
        }

        /// <summary>
        /// 
        /// </summary>
        public void Add(DirectionalLight d)
        {
            directionalLights.Add(d);
            DirectionalLightAdded(d);
        }

        /// <summary>
        /// 
        /// </summary>
        public void Add(AmbientLight a)
        {
            ambientLights.Add(a);
            AmbientLightAdded(a);
        }

        /// <summary>
        /// 
        /// </summary>
        public void Add(PointLight p)
        {
            pointLights.Add(p);
            PointLightAdded(p);
        }

        /// <summary>
        /// 
        /// </summary>
        public void Add(SpotLight p)
        {
            spotLights.Add(p);
            SpotLightAdded(p);
        }

        /// <summary>
        /// 
        /// </summary>
        public void Add(Terrain t)
        {
            terrains.Add(t);
            TerrainAdded(t);
        }

        /// <summary>
        /// 
        /// </summary>
        public void Delete(DrawableObject o)
        {
            objects.Remove(o);
            DrawableObjectDeleted(o);
        }

        /// <summary>
        /// 
        /// </summary>
        public void Delete(DirectionalLight d)
        {
            directionalLights.Remove(d);
            DirectionalLightDeleted(d);
        }

        /// <summary>
        /// 
        /// </summary>
        public void Delete(AmbientLight a)
        {
            ambientLights.Remove(a);
            AmbientLightDeleted(a);
        }

        /// <summary>
        /// 
        /// </summary>
        public void Delete(PointLight p)
        {
            pointLights.Remove(p);
            PointLightDeleted(p);
        }

        /// <summary>
        /// 
        /// </summary>
        public void Delete(SpotLight p)
        {
            spotLights.Remove(p);
            SpotLightDeleted(p);
        }

        /// <summary>
        /// 
        /// </summary>
        public void Delete(Terrain t)
        {
            terrains.Remove(t);
            TerrainDeleted(t);
        }
        #endregion
    }
}
